/**
 * hook_demo.c - 钩子框架全面演示程序
 *
 * 这个程序演示了钩子框架的主要功能，包括文件操作、网络连接、进程管理等
 * 可以与各种类型的插件一起使用，展示钩子拦截机制
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <pthread.h>
#include <signal.h>
#include <time.h>

/* 测试文件路径 */
#define TEST_FILE "/tmp/hook_demo.txt"
#define TEST_DIR "/tmp/hook_demo_dir"
#define TEST_LOG "/tmp/hook_demo.log"
#define TEST_BIN "/tmp/hook_demo.bin"
#define TEST_CONFIG "/tmp/hook_demo.conf"

/* 测试内容 */
#define TEST_DATA "这是测试数据，用于演示钩子框架的功能。"
#define CONFIG_CONTENT "[Settings]\nlog_level=info\nenable_debug=true\nuser=admin\n"

/* 演示文件操作钩子 */
void demo_file_operations() {
    printf("\n===== 演示文件操作钩子 =====\n");
    
    /* 创建目录 */
    printf("创建目录: %s\n", TEST_DIR);
    mkdir(TEST_DIR, 0755);
    
    /* 创建并写入文件 */
    printf("创建文件: %s\n", TEST_FILE);
    int fd = open(TEST_FILE, O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if (fd >= 0) {
        write(fd, TEST_DATA, strlen(TEST_DATA));
        close(fd);
        printf("写入了 %zu 字节数据\n", strlen(TEST_DATA));
    }
    
    /* 读取文件 */
    printf("读取文件: %s\n", TEST_FILE);
    fd = open(TEST_FILE, O_RDONLY);
    if (fd >= 0) {
        char buffer[256] = {0};
        ssize_t bytes = read(fd, buffer, sizeof(buffer) - 1);
        close(fd);
        printf("读取了 %zd 字节数据: %s\n", bytes, buffer);
    }
    
    /* 使用标准I/O操作 */
    printf("使用标准I/O写入文件: %s\n", TEST_CONFIG);
    FILE* fp = fopen(TEST_CONFIG, "w");
    if (fp) {
        fputs(CONFIG_CONTENT, fp);
        fclose(fp);
        printf("写入了配置数据\n");
    }
    
    printf("使用标准I/O读取文件: %s\n", TEST_CONFIG);
    fp = fopen(TEST_CONFIG, "r");
    if (fp) {
        char line[128];
        while (fgets(line, sizeof(line), fp)) {
            printf("  读取配置行: %s", line);
        }
        fclose(fp);
    }
    
    /* 文件权限操作 */
    printf("修改文件权限: %s\n", TEST_FILE);
    chmod(TEST_FILE, 0600);
    
    /* 创建二进制文件 */
    printf("创建二进制文件: %s\n", TEST_BIN);
    unsigned char binary_data[256];
    for (int i = 0; i < 256; i++) {
        binary_data[i] = (unsigned char)i;
    }
    
    fd = open(TEST_BIN, O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if (fd >= 0) {
        write(fd, binary_data, sizeof(binary_data));
        close(fd);
        printf("写入了 %zu 字节二进制数据\n", sizeof(binary_data));
    }
}

/* 演示网络操作钩子 */
void demo_network_operations() {
    printf("\n===== 演示网络操作钩子 =====\n");
    
    /* 创建套接字 */
    printf("创建套接字\n");
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0) {
        perror("socket");
        return;
    }
    
    /* 连接到本地服务器 */
    printf("尝试连接到本地地址: 127.0.0.1:8080\n");
    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(8080);
    inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr);
    
    /* 连接可能会失败，但这足以触发钩子 */
    connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr));
    
    /* 尝试发送数据 */
    const char* send_data = "GET / HTTP/1.1\r\nHost: localhost\r\n\r\n";
    printf("尝试发送HTTP请求数据\n");
    send(sock, send_data, strlen(send_data), 0);
    
    /* 尝试接收数据 */
    printf("尝试接收响应数据\n");
    char recv_buffer[512];
    recv(sock, recv_buffer, sizeof(recv_buffer), 0);
    
    /* 尝试连接到外部服务器 */
    printf("尝试连接到外部地址: 8.8.8.8:53 (谷歌DNS)\n");
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(53);
    inet_pton(AF_INET, "8.8.8.8", &server_addr.sin_addr);
    
    /* 连接可能会失败，但这足以触发钩子 */
    connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr));
    
    /* 关闭套接字 */
    close(sock);
}

/* 演示进程操作钩子 */
void demo_process_operations() {
    printf("\n===== 演示进程操作钩子 =====\n");
    
    /* 获取进程信息 */
    printf("进程ID: %d\n", getpid());
    printf("父进程ID: %d\n", getppid());
    
    /* 执行系统命令 */
    printf("执行系统命令: ls -la /tmp\n");
    system("ls -la /tmp");
    
    /* Fork进程 */
    printf("尝试创建子进程\n");
    pid_t pid = fork();
    
    if (pid == 0) {
        /* 子进程 */
        printf("这是子进程 (PID: %d)\n", getpid());
        exit(0);
    } else if (pid > 0) {
        /* 父进程 */
        printf("这是父进程，创建了子进程 (PID: %d)\n", pid);
        int status;
        waitpid(pid, &status, 0);
    }
    
    /* 修改进程优先级 */
    printf("修改进程优先级\n");
    nice(10);
}

/* 演示内存操作钩子 */
void demo_memory_operations() {
    printf("\n===== 演示内存操作钩子 =====\n");
    
    /* 动态内存分配 */
    printf("分配内存: malloc(1024)\n");
    void* ptr1 = malloc(1024);
    if (ptr1) {
        memset(ptr1, 'A', 1024);
        printf("向内存写入数据\n");
    }
    
    printf("分配内存: calloc(100, 20)\n");
    void* ptr2 = calloc(100, 20);
    
    printf("重新分配内存: realloc()\n");
    if (ptr1) {
        ptr1 = realloc(ptr1, 2048);
        printf("扩展内存大小到2048字节\n");
    }
    
    /* 释放内存 */
    printf("释放内存: free()\n");
    if (ptr1) free(ptr1);
    if (ptr2) free(ptr2);
}

/* 演示多线程操作钩子 */
void* thread_function(void* arg) {
    printf("线程 #%ld 开始执行\n", (long)arg);
    
    /* 执行一些文件操作 */
    char filename[64];
    sprintf(filename, "/tmp/thread_%ld.txt", (long)arg);
    
    FILE* fp = fopen(filename, "w");
    if (fp) {
        fprintf(fp, "这是线程 #%ld 创建的文件\n", (long)arg);
        fclose(fp);
        printf("线程 #%ld 创建了文件: %s\n", (long)arg, filename);
    }
    
    /* 延迟退出 */
    usleep(100000);
    
    printf("线程 #%ld 结束执行\n", (long)arg);
    return NULL;
}

void demo_thread_operations() {
    printf("\n===== 演示线程操作钩子 =====\n");
    
    /* 创建多个线程 */
    #define NUM_THREADS 3
    pthread_t threads[NUM_THREADS];
    
    printf("创建 %d 个线程\n", NUM_THREADS);
    
    for (long i = 0; i < NUM_THREADS; i++) {
        if (pthread_create(&threads[i], NULL, thread_function, (void*)i) != 0) {
            perror("pthread_create");
        }
    }
    
    /* 等待线程完成 */
    printf("等待线程完成\n");
    for (int i = 0; i < NUM_THREADS; i++) {
        pthread_join(threads[i], NULL);
    }
    
    printf("所有线程已完成\n");
}

/* 清理测试文件 */
void cleanup_test_files() {
    printf("\n===== 清理测试文件 =====\n");
    
    unlink(TEST_FILE);
    unlink(TEST_BIN);
    unlink(TEST_CONFIG);
    rmdir(TEST_DIR);
    
    /* 清理线程创建的文件 */
    for (int i = 0; i < 3; i++) {
        char filename[64];
        sprintf(filename, "/tmp/thread_%d.txt", i);
        unlink(filename);
    }
    
    printf("所有测试文件已清理\n");
}

int main(int argc, char* argv[]) {
    printf("===== 钩子框架演示程序 =====\n");
    printf("这个程序演示了各种可被钩子拦截的操作\n\n");
    
    /* 获取环境变量 */
    const char* preload = getenv("LD_PRELOAD");
    printf("LD_PRELOAD: %s\n", preload ? preload : "未设置");
    
    /* 运行演示 */
    demo_file_operations();
    demo_network_operations();
    demo_process_operations();
    demo_memory_operations();
    demo_thread_operations();
    
    /* 清理 */
    cleanup_test_files();
    
    printf("\n===== 演示完成 =====\n");
    return 0;
} 